﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ZZT
{
    public class Pointer
    {
        static private Encoding encoding = Encoding.GetEncoding(437);
        private byte[] memory;
        private int offset;

        public Pointer(int length)
        {
            this.memory = new byte[length];
            this.offset = 0;
        }

        public Pointer(byte[] memory, int offset)
        {
            this.memory = memory;
            this.offset = offset;
        }

        virtual public byte this[int index]
        {
            get { return memory[index]; }
            set { memory[index] = value; }
        }

        public bool Bool
        {
            get
            {
                return this[0] != 0;
            }
            set
            {
                this[0] = (byte)(value ? 1 : 0);
            }
        }

        public byte Byte
        {
            get
            {
                return this[0];
            }
            set
            {
                this[0] = (byte)(value & 0xFF);
            }
        }

        public bool Compare(byte[] value)
        {
            for (int i = 0; i < value.Length; i++)
            {
                if (memory[offset + i] != value[i])
                    return false;
            }
            return true;
        }

        public bool Compare(string value)
        {
            return Compare(EncodeString(value));
        }

        string DecodeString()
        {
            byte[] result = new byte[memory[offset]];
            Array.Copy(memory, offset + 1, result, 0, result.Length);
            return encoding.GetString(result);
        }

        byte[] EncodeString(string value)
        {
            byte[] convertedString = new byte[value.Length + 1];
            Array.Copy(encoding.GetBytes(value), 0, convertedString, 1, value.Length);
            convertedString[0] = (byte)(value.Length & 0xFF);
            return convertedString;
        }

        public byte[] Extract(int offset, int length)
        {
            byte[] result = new byte[length];
            Array.Copy(memory, this.offset + offset, result, 0, length);
            return result;
        }

        public Pointer GetRelativePointer(int offset)
        {
            return new Pointer(memory, this.offset + offset);
        }

        virtual public int Int8
        {
            get
            {
                return memory[0];
            }
            set
            {
                memory[0] = (byte)(value & 0xFF);
            }
        }

        virtual public int Int16
        {
            get
            {
                Int16 result = (Int16)memory[1];
                result <<= 8;
                result |= (Int16)memory[0];
                return result;
            }
            set
            {
                memory[0] = (byte)(value & 0xFF);
                value >>= 8;
                memory[1] = (byte)(value & 0xFF);
            }
        }

        virtual public int Int32
        {
            get
            {
                Int32 result = (Int32)memory[3];
                result <<= 8;
                result |= (Int32)memory[2];
                result <<= 8;
                result |= (Int32)memory[1];
                result <<= 8;
                result |= (Int32)memory[0];
                return result;
            }
            set
            {
                memory[0] = (byte)(value & 0xFF);
                value >>= 8;
                memory[1] = (byte)(value & 0xFF);
                value >>= 8;
                memory[2] = (byte)(value & 0xFF);
                value >>= 8;
                memory[3] = (byte)(value & 0xFF);
            }
        }

        virtual public string String
        {
            get
            {
                return DecodeString();
            }
            set
            {
                byte[] result = EncodeString(value);
                Array.Copy(result, 0, memory, offset, result.Length);
            }
        }
    }
}
